package com.li.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.li.result.Result;
import com.li.result.ResultCodeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.li.entities.Product;

import java.util.ArrayList;
import java.util.List;
@RestController
@Slf4j
@Tag(name="聚划算模拟商品上下架")
public class JHSTaskController {
        public static final String JHS_KEY = "jhs";
        public static final String JHS_KEY_A = "jhs:a";
        public static final String JHS_KEY_B = "jhs:b";

        @Autowired
        private RedisTemplate<String, Object> redisTemplate;

        @Operation(summary = "聚划算案例，每次1页，每页5条数据")
        @GetMapping("/product/find")
        public Result find(int page, int size) {
            List<Product> list = new ArrayList<>();
            long start = (long) (page - 1) * size;
            long end = start + size - 1;
            try {
                //利用lrange实现分页查询
                List<Object> rawList = redisTemplate.opsForList().range(JHS_KEY, start, end);
                if (CollectionUtils.isEmpty(rawList)) {
                    // todo Redis找不到，去数据库中查询
                   return Result.build(null,
                           ResultCodeEnum.CALLBACK_REQUEST.getCode(),"查询MySQL");
                }
                ObjectMapper objectMapper = new ObjectMapper();
                //类型转换
                for (Object obj : rawList) {
                    Product product = objectMapper.convertValue(obj, Product.class);
                    list.add(product);
                }
                log.info("参加活动的商家: {}", list);
            } catch (Exception e) {
                //出异常,一般redis宕机或网络抖动导致timeout
                log.error("redis异常: {}", e.getMessage());
                //如果有业务需求,需要强查询,这里查询MySQL
                throw new RuntimeException(e);
            }
            return Result.ok(list);
        }
    @GetMapping(value = "/product/findab")
    @Operation(summary = "防止热点key突然失效，AB双缓存架构")
    public Result findAB(int page, int size) {
        List<Product> list= new ArrayList<>();
        long start = (long) (page - 1) * size;
        long end = start + size - 1;
        try {
            //采用redis list数据结构的lrange命令实现分页查询
            List<Object> rawList = redisTemplate.opsForList().range(JHS_KEY_A, start, end);
            if (CollectionUtils.isEmpty(rawList)) {
                log.info("=========A缓存已经失效了，记得人工修补，B缓存自动延续5天");
                //用户先查询缓存A(上面的代码)，如果缓存A查询不到（例如，更新缓存的时候删除了），再查询缓存B
                this.redisTemplate.opsForList().range(JHS_KEY_B, start, end);
                //TODO 走DB查询
                return Result.build(null,
                        ResultCodeEnum.CALLBACK_REQUEST.getCode(),"查询MySQL");
            }
            ObjectMapper objectMapper = new ObjectMapper();
            log.info("查询结果：{}", rawList);
            for (Object obj : rawList) {
                Product product = objectMapper.convertValue(obj, Product.class);
                list.add(product);
            }
        } catch (Exception ex) {
            //这里的异常，一般是redis瘫痪 ，或 redis网络timeout
            log.error("exception:", ex);
            //TODO 走DB查询
        }
        return Result.ok(list);
    }
}
